package cn.loan.tools;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.internal.Primitives;

import java.util.*;

/**
 * @Author: 毛苏宇
 * @Description: You can do it!    Json与Java复杂类型的相互转换
 * 1.Json转Java对象
 * 2.对象转Json字符串
 * 3.Json转List集合
 * 4.List集合转Json
 * 5.Json转Set集合
 * 6.Set集合转Json
 * 7.Json转Map集合
 * 8.Map集合转Json
 * @Date: Create in 16:50 2019/2/20
 */

/*<!--Json转换需要的依赖-->
    <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.5</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.3</version>
    </dependency>
*/
public class GsonTool {

    private static final Gson gson = new GsonBuilder()
            .serializeNulls()   //当字段值为空或null时，依然对该字段进行转换
            .disableHtmlEscaping()  //防止特殊字符出现乱码
            .setPrettyPrinting()    //对结果进行换行
            .setDateFormat("yyyy-MM-dd HH:mm:ss:SSS") //时间转化为特定格式
            .create();


    /**
     * Java对象转为Json
     *
     * @param object
     * @return 返回Json
     */
    public static String objectToJson(Object object) {
        return gson.toJson(object);
    }


    /**
     * List集合转Json
     *
     * @param list List集合
     * @return 返回Json
     */
    public static String listToJson(List list) {
        return gson.toJson(list);
    }


    /**
     * map集合转Json
     *
     * @param map map集合
     * @return 返回Json
     */
    public static String mapToJson(Map map) {
        return gson.toJson(map);
    }


    /**
     * set集合转Json
     *
     * @param set set集合
     * @return 返回Json
     */
    public static String setToJson(Set set) {
        return gson.toJson(set);
    }


    /**
     * Json转Java对象
     *
     * @param json      Json字符串
     * @param typeClass 对象类类型
     * @return 返回Java对象
     */
    public static <T> T jsonToObject(String json, Class<?> typeClass) {
        //先转为Object
        Object object = gson.fromJson(json, typeClass);
        //再把Object转为泛型T
        T t = (T) Primitives.wrap(typeClass).cast(object);
        //返回该泛型,无需做类型转换
        return t;
    }


    /**
     * Json转List集合,当对象中存在Date类型时请使用@JsonFormat( pattern="yyyy-MM-dd HH:mm:ss:SSS")注解修饰该Date属性
     *
     * @param json      Json字符串
     * @param typeClass 类类型
     * @return 返回List集合
     */
    public static List jsonToList(String json, Class<?> typeClass) {
        //ObjectMapper将转换成Java对象匹配JSON结构
        ObjectMapper mapper = new ObjectMapper();
        //得到Java类型
        JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, typeClass);
        try {
            //将json中的数据装配到该结构中并返回
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            //出错则返回
            return null;
        }
    }


    /**
     * Json转Set集合
     *
     * @param json      Json字符串
     * @param typeClass 类类型
     * @return 返回Set集合
     */
    public static Set jsonToSet(String json, Class<?> typeClass) {
        //ObjectMapper将转换成Java对象匹配JSON结构
        ObjectMapper mapper = new ObjectMapper();
        //得到Java类型
        JavaType javaType = mapper.getTypeFactory().constructParametricType(Set.class, typeClass);
        try {
            //将json中的数据装配到该结构中并返回
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            //出错则返回
            return null;
        }
    }


    /**
     * Json转Map集合
     *
     * @param json           Json字符串
     * @param keyTypeClass   key的类类型
     * @param valueTypeClass 值的类类型
     * @return 返回map集合
     */
    public static Map jsonToMap(String json, Class<?> keyTypeClass, Class<?> valueTypeClass) {
        //ObjectMapper将转换成Java对象匹配JSON结构
        ObjectMapper mapper = new ObjectMapper();
        //得到Java类型
        JavaType javaType = mapper.getTypeFactory().constructParametricType(Map.class, keyTypeClass, valueTypeClass);
        try {
            //将json中的数据装配到该结构中并返回
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            //出错则返回
            return null;
        }
    }

}
